package cn.edu.xmu.oomall.liquidation.service;

import cn.edu.xmu.oomall.core.util.ReturnNo;
import cn.edu.xmu.oomall.core.util.ReturnObject;
import cn.edu.xmu.oomall.liquidation.dao.LiquidationDao;
import cn.edu.xmu.oomall.liquidation.microservice.AfterSaleService;
import cn.edu.xmu.oomall.liquidation.microservice.OrderService;
import cn.edu.xmu.oomall.liquidation.microservice.PaymentService;
import cn.edu.xmu.oomall.liquidation.microservice.vo.*;
import cn.edu.xmu.oomall.liquidation.model.bo.Liquidation;
import cn.edu.xmu.oomall.liquidation.model.bo.StartInfo;
import cn.edu.xmu.oomall.liquidation.model.bo.liquid.calc.CalcTotal;
import cn.edu.xmu.oomall.liquidation.model.bo.liquid.expenditure.AfterSaleRefundLiquid;
import cn.edu.xmu.oomall.liquidation.model.bo.liquid.expenditure.OrderRefundLiquid;
import cn.edu.xmu.oomall.liquidation.model.bo.liquid.revenue.AfterSalePaymentLiquid;
import cn.edu.xmu.oomall.liquidation.model.bo.liquid.revenue.OrderPaymentLiquid;
import cn.edu.xmu.oomall.liquidation.model.bo.liquid.util.LiquidUtil;
import cn.edu.xmu.oomall.liquidation.model.vo.StartInfoVo;
import com.github.pagehelper.PageInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.List;
import java.util.stream.Collectors;

import static cn.edu.xmu.privilegegateway.annotation.util.Common.cloneVo;

@Service
public class StartLiquidationService {
    @Autowired
    private LiquidUtil liquidUtil;

    @Autowired
    private OrderPaymentLiquid orderPaymentLiquid;

    @Autowired
    private AfterSalePaymentLiquid afterSalePaymentLiquid;

    @Autowired
    private OrderRefundLiquid orderRefundLiquid;

    @Autowired
    private AfterSaleRefundLiquid afterSaleRefundLiquid;

    private Logger logger = LoggerFactory.getLogger(LiquidationService.class);

    @Transactional(rollbackFor = Exception.class)
    public ReturnObject startLiquidations(StartInfoVo startInfoVo, Long userId, String userName) {
        Integer pageSize = 50;
        StartInfo startInfo = cloneVo(startInfoVo, StartInfo.class);

        liquidUtil.setCreator(userId, userName);

        // 获得当前清算日期
        LocalDateTime liquidDateTime = startInfoVo.getBeginTime().withZoneSameInstant(ZoneId.systemDefault()).toLocalDateTime();
        liquidDateTime = LocalDateTime.of(liquidDateTime.toLocalDate(), LocalTime.MIN);
        startInfo.setLiquidDateTime(liquidDateTime);

        CalcTotal platformCalcTotal = new CalcTotal(liquidUtil.getPlatformCalcFieldList());
        CalcTotal paymentTotal = liquidPayment(startInfo, pageSize);
        CalcTotal refundTotal = liquidRefund(startInfo, pageSize);

        platformCalcTotal.add(paymentTotal);
        platformCalcTotal.add(refundTotal);

        // 生成平台清算单
        generatePlatformLiquid(liquidDateTime, platformCalcTotal);

        return new ReturnObject(ReturnNo.OK);
    }

    private Liquidation generatePlatformLiquid(LocalDateTime liquidDateTime, CalcTotal platformCalcTotal) {
        Liquidation platformLiquidation = new Liquidation();
        platformLiquidation.setShopId(0L);
        platformLiquidation.setLiquidDate(liquidDateTime);
        platformLiquidation.setExpressFee(platformCalcTotal.get("expressFee"));
        platformLiquidation.setCommission(platformCalcTotal.get("commission"));
        platformLiquidation.setShopRevenue(platformCalcTotal.get("expressFee") + platformCalcTotal.get("commission"));

        liquidUtil.insertLiquidation(platformLiquidation);
        return platformLiquidation;
    }

    private CalcTotal liquidPayment(StartInfo startInfo, Integer pageSize) {
        LocalDateTime liquidDateTime = startInfo.getLiquidDateTime();
        CalcTotal paymentCalcTotal = new CalcTotal(liquidUtil.getPlatformCalcFieldList());
        // 查询数据总页数
        PageInfo<PaymentRetVo> data = liquidUtil.getPaymentByTime(startInfo.getBeginTime(), startInfo.getEndTime(), 1, pageSize).getData();
        Integer pages = data.getPages();

        List<PaymentRetVo> paymentRetVoList;
        //开始清算支付单
        for (int page = 1; page <= pages;page++) {
            paymentRetVoList = liquidUtil.getPaymentByTime( startInfo.getBeginTime(), startInfo.getEndTime(),page, pageSize).getData().getList();

            // 去除保证金
            paymentRetVoList = paymentRetVoList.stream().filter(x -> x.getDocumentType() != 1).collect(Collectors.toList());
            // 过滤出订单支付单和售后支付单
            List<PaymentRetVo> orderPaymentList = paymentRetVoList.stream().filter(x -> x.getDocumentType() != 4).collect(Collectors.toList());
            List<PaymentRetVo> afterSalePaymentList = paymentRetVoList.stream().filter(x -> x.getDocumentType() == 4).collect(Collectors.toList());
            //清算订单支付单
            CalcTotal orderCalc = orderPaymentLiquid.liquidate(orderPaymentList, liquidDateTime);
            //清算售后支付单
            CalcTotal afterSaleCalc = afterSalePaymentLiquid.liquidate(afterSalePaymentList, liquidDateTime);

            //统计数据
            paymentCalcTotal.add(orderCalc);
            paymentCalcTotal.add(afterSaleCalc);
        }
        return paymentCalcTotal;
    }

    private CalcTotal liquidRefund(StartInfo startInfo, Integer pageSize) {
        LocalDateTime liquidDateTime = startInfo.getLiquidDateTime();
        CalcTotal refundCalcTotal = new CalcTotal(liquidUtil.getPlatformCalcFieldList());
        // 查询数据总页数
        PageInfo<RefundRetVo> refundData = liquidUtil.getRefundByTime(startInfo.getBeginTime(), startInfo.getEndTime(), 1, pageSize).getData();
        Integer pages = refundData.getPages();

        //清算退款单
        List<RefundRetVo> refundRetVoList;
        for (int page = 1; page <= pages;page++) {
            refundRetVoList = liquidUtil.getRefundByTime(startInfo.getBeginTime(), startInfo.getEndTime(),1, pageSize).getData().getList();
            List<RefundRetVo> orderRefundList = refundRetVoList.stream().filter(x -> x.getDocumentType() == 0).collect(Collectors.toList());
            List<RefundRetVo> aftersaleRefundList = refundRetVoList.stream().filter(x -> x.getDocumentType() == 2).collect(Collectors.toList());
            // 清算订单退款
            CalcTotal orderCalc = orderRefundLiquid.liquidate(orderRefundList, liquidDateTime);
            // 清算售后退款
            CalcTotal afterSaleCalc = afterSaleRefundLiquid.liquidate(aftersaleRefundList, liquidDateTime);

            refundCalcTotal.add(orderCalc);
            refundCalcTotal.add(afterSaleCalc);
        }
        return refundCalcTotal;
    }
}